package Adding_score_item;

import week3.Chapter5.jsjf.QueueADT;
import week3.Chapter5.jsjf.exceptions.EmptyCollectionException;

import java.util.Scanner;

/**
 * CircularArrayQueue represents an array implementation of a queue in
 * which the indexes for the front and rear of the queue circle back to 0
 * when they reach the end of the array.
 *
 * @author Lewis and Chase
 * @version 4.0
 */
public  class Circular_queue<T> implements QueueADT<T>
{
    private final static int DEFAULT_CAPACITY = 100;
    private int front, rear, count;
    private T[] queue;

    /**
     * Creates an empty queue using the specified capacity.
     * @param initialCapacity the initial size of the circular array queue
     */
    public Circular_queue(int initialCapacity)
    {
        front = rear = count = 0;
        queue = (T[]) (new Object[initialCapacity]);
    }

    /**
     * Creates an empty queue using the default capacity.
     */
    public Circular_queue()
    {
        this(DEFAULT_CAPACITY);
    }

    /**
     * Adds the specified element to the rear of this queue, expanding
     * the capacity of the queue array if necessary.
     * @param element the element to add to the rear of the queue
     */
    @Override
    public void enqueue(T element)
    {
        if (size() == queue.length) {
            expandCapacity();
        }

        queue[rear] = element;
        rear = (rear+1) % queue.length;

        count++;
    }

    /**
     * Creates a new array to store the contents of this queue with
     * twice the capacity of the old one.
     */
    private void expandCapacity()
    {
        T[] larger = (T[]) (new Object[queue.length *2]);

        for (int scan = 0; scan < count; scan++)
        {
            larger[scan] = queue[front];
            front = (front + 1) % queue.length;
        }

        front = 0;
        rear = count;
        queue = larger;
    }

    /**
     * Removes the element at the front of this queue and returns a
     * reference to it.
     * @return the element removed from the front of the queue
     * @throws EmptyCollectionException  if the queue is empty
     */
    @Override
    public T dequeue() throws EmptyCollectionException
    {
        if (isEmpty()) {
            throw new EmptyCollectionException("queue");
        }

        T result = queue[front];
        queue[front] = null;
        front = (front+1) % queue.length;

        count--;

        return result;
    }

    /**
     * Returns a reference to the element at the front of this queue.
     * The element is not removed from the queue.
     * @return the first element in the queue
     * @throws EmptyCollectionException if the queue is empty
     */
    @Override
    public T first() throws EmptyCollectionException
    {
        // To be completed as a Programming Project
        if (isEmpty()) {
            throw new EmptyCollectionException("queue");
        }
        T result = queue[front];
//        queue[front] = null;
//        front = (front+1) % queue.length;
        return result;
    }

    /**
     * Returns true if this queue is empty and false otherwise.
     * @return true if this queue is empty
     */
    @Override
    public boolean isEmpty()
    {
        // To be completed as a Programming Project
        if (count==0){
            return true;
        }
        else {
            return false;
        }
    }

    /**
     * Returns the number of elements currently in this queue.
     * @return the size of the queue
     */
    @Override
    public int size()
    {
        // To be completed as a Programming Project
        return count;
    }

    /**
     * Returns a string representation of this queue.
     * @return the string representation of the queue
     */
    @Override
    public String toString()
    {
        // To be completed as a Programming Project
        String result = "";
        int head = front;
        if(queue[head]==null){
            return "";
        }
        else {
            for (int i = 0 ; i < count; i++)
            {
                result += queue[head] + " ";
                queue[head] = null;
                head = (head+1) % queue.length;
            }
            return result;
        }
//        String str = "";
//        if (front == rear) {
//            str = "  ";
//        } else if (front < rear) {
//            for (int i = front; i < rear; i++)
//            {
//                str += queue[i] + " ";
//            }
//        } else if (front > rear) {
//            for (int i = front; i < DEFAULT_CAPACITY; i++) {
//                str += queue[i] + " ";
//            }
//            for (int i = 0; i < rear; i++) {
//                str += queue[i] + " ";
//            }
//        }
//
//        str = str.substring(0,str.length()-2);
//
//        str += " ";
//
//        return str;

    }

    public static void main(String[] args) {
        System.out.println("Please enter the number of lines to display for the Yang hui triangle:");
        Scanner scanner = new Scanner(System.in);
        int line = scanner.nextInt(),first,temp;
        Circular_queue circular_queue = new Circular_queue();
        circular_queue.enqueue(1);
        for (int i = 0 ; i < line; i++){
                circular_queue.enqueue(1);

                for (int j = 0; j < i; j++) {
                    temp = (int) circular_queue.dequeue();
                    System.out.printf(   temp+"\t"  );
                    temp = temp + (int) circular_queue.first();
                    circular_queue.enqueue(temp);
                }
                first = (int)circular_queue.dequeue();
                System.out.printf(  first+ "\t"  );
                circular_queue.enqueue(1);
                System.out.println();
            }
    }
}